
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#include "helper.h"
#include <vector>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>

using namespace std;

/**
 * Trims leading and trailing whitespace characters,
 *   including space, tab, and new lines
 *
 */
inline std::string trimStr(std::string& str)
{
  str.erase(0, str.find_first_not_of(" \t\r\n"));
  str.erase(str.find_last_not_of(" \t\r\n")+1);         
  return str;
}


struct qr readqueryrangeFile(const char* fp, int p, int d)
{
   qr queryrange;
   queryrange.min = new double[d*p];
   queryrange.max = new double[d*p];
/*   int dim=0;
   queryrange = new struct qr[p];
   for(int i=0; i< p; i++)
   {
        queryrange[i].min = new double[d];
        queryrange[i].max = new double[d];
   }*/

  string line;
   
  int lineI = 0;

  ifstream myfile(fp);
  if (myfile.is_open())
  {

    while ( myfile.good() )
    {

      int tokI = 0;
      char* tokStr = NULL;
      char* lineStr = NULL;
      getline(myfile,line);
      line = trimStr(line);
      if(line.length() != 0)
      {
         


		  tokI = 0;
		  tokStr = NULL;
		  lineStr = new char[line.length()+1]; //+1 for auto added null terminator
		  strcpy(lineStr, line.c_str());

		  tokStr = strtok(lineStr, ",");
		  while (tokStr != NULL)
		  {
			  //cout << "Min: tokI: "<<tokI << " lineI " << lineI <<" tokStr " << tokStr <<endl;
			  queryrange.min[tokI + lineI]=strtod(tokStr, NULL);
			  tokStr = strtok(NULL, ",");
			  tokI++;
		  }
      }
      if(myfile.good());
      getline(myfile,line);
      line = trimStr(line);
      if(line.length() != 0)
	  {

    	  tokI=0;
		  tokStr= NULL;
		  lineStr = NULL;
		  lineStr = new char[line.length()+1];
		  strcpy(lineStr, line.c_str());

		  tokStr = strtok(lineStr, ",");
		  while (tokStr != NULL)
		  {
			//cout << "Max: tokI: "<<tokI << " lineI " << lineI <<" tokStr " << tokStr <<endl;
			queryrange.max[tokI + lineI]=strtod(tokStr, NULL);
			tokStr = strtok(NULL, ",");
			tokI++;
		  }
      }
      lineI = lineI + d; //first line is 0
    }

    myfile.close();
  }
  else
  {
    cout << "Unable to open file" << endl;
  }

  
  return queryrange;
}


double** readqueryKnnFile(const char* fp, int p, int d)
{
     //pointer to hold address of array values for a two dimensional data
    double* array_data;
    //pointer to two dimensional arrays, that holds the actual data
    double** data;


  //double* data = NULL; //this will hold the entire 2D data array

  string line;
  int lineI = -1;

  ifstream myfile(fp);
  if (myfile.is_open())
  {
    //data = new double[p*d]; // initialize data array
      array_data = new double[p*d];
    data = new double*[p];
    for (int i = 0; i < p; ++i)
    data[i] = array_data + d*i;

    while ( myfile.good() )
    {
      getline(myfile,line);
      line = trimStr(line);
          if(line.length() != 0)
      {
      lineI = lineI + 1; //first line is 0

      int tokI = 0;
      char* tokStr = NULL;
      char* lineStr = new char[line.length()+1]; //+1 for auto added null terminator
      strcpy(lineStr, line.c_str());

      tokStr = strtok(lineStr, ",");
      while (tokStr != NULL)
      {

          data[lineI][tokI]=strtod(tokStr, NULL);

        tokStr = strtok(NULL, ",");
        tokI++;
      }
      }
    }

    myfile.close();
  }
  else
  {
    cout << "Unable to open file" << endl;
  }

  return data;

}

double** readquerypointFile(const char* fp, int p, int d)
{
     //pointer to hold address of array values for a two dimensional data
    double* array_data;
    //pointer to two dimensional arrays, that holds the actual data
    double** data;


  //double* data = NULL; //this will hold the entire 2D data array

  string line;
  int lineI = -1;

  ifstream myfile(fp);
  if (myfile.is_open())
  {
    //data = new double[p*d]; // initialize data array
      array_data = new double[p*d];
    data = new double*[p];
    for (int i = 0; i < p; ++i)
    data[i] = array_data + d*i;

    while ( myfile.good() )
    {
      getline(myfile,line);
      line = trimStr(line);
          if(line.length() != 0)
      {
      lineI = lineI + 1; //first line is 0

      int tokI = 0;
      char* tokStr = NULL;
      char* lineStr = new char[line.length()+1]; //+1 for auto added null terminator
      strcpy(lineStr, line.c_str());

      tokStr = strtok(lineStr, ",");
      while (tokStr != NULL)
      {

          data[lineI][tokI]=strtod(tokStr, NULL);

        tokStr = strtok(NULL, ",");
        tokI++;
      }
      }
    }

    myfile.close();
  }
  else
  {
    cout << "Unable to open file" << endl;
  }

  return data;

}


double** readDataFile(const char* fp, int p, int d)
{
  /* Sample file line:
   * id, dim1, dim2, dim3, ...
   * uniform: 0,0.0173,0.3729,0.1081,0.0466,0.5339,0.3966,0.3892,0.6968,0.8678,0.5521,0.3693,0.8507,0.0219,0.6543,0.5903,0.8401
   * cluster: 0,0.7578,0.8032,0.7382,0.309,0.4025,0.3287,0.1351,0.6352,0.2762,0.4595,0.523,0.6555,0.159,0.8006,0.8809,0.2546
   * real: 155,0.3132,0.4807,0.4896,0.3274,0.3117,0.5368,0.6084,0.4306,0.2527,0.4752,0.3269,0.3477,0.2661,0.2839,0.2907,0.2188
   */

  //pointer to hold address of array values for a two dimensional data
    double* array_data;
    //pointer to two dimensional arrays, that holds the actual data
    double** data;

    
  //double* data = NULL; //this will hold the entire 2D data array

  string line;
  int lineI = -1;

  ifstream myfile(fp);
  if (myfile.is_open())
  {
    //data = new double[p*d]; // initialize data array
      array_data = new double[p*d];
    data = new double*[p];
    for (int i = 0; i < p; ++i)
    data[i] = array_data + d*i;

    while ( myfile.good() )
    {
      getline(myfile,line);
      line = trimStr(line);
          if(line.length() != 0)
      {
      lineI = lineI + 1; //first line is 0

      int tokI = 0;
      char* tokStr = NULL;
      char* lineStr = new char[line.length()+1]; //+1 for auto added null terminator
      strcpy(lineStr, line.c_str());

      tokStr = strtok(lineStr, ",");
      while (tokStr != NULL)
      {
       
          data[lineI][tokI]=strtod(tokStr, NULL);

        tokStr = strtok(NULL, ",");
        tokI++;
      }
      }
    }

    myfile.close();
  }
  else
  {
    cout << "Unable to open file" << endl;
  }

  return data;

}




int* getFileInfo(const char* fp)
{
  string line;
  int lineI = 0;
  int valC = 0;

  ifstream myfile(fp);
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline(myfile,line);
      line = trimStr(line);
          if(line.length() != 0)
      {
      lineI = lineI + 1;
     // cout<<line << "end of line \n";

      if(lineI == 1) //get dims too
      {
        char* pch = NULL;
        char* str = new char[line.length()+1]; //+1 for auto added null terminator
        strcpy(str, line.c_str());

        pch = strtok(str, ",");
        while (pch != NULL)
        {
          pch = strtok (NULL, ",");
          valC++;
        }
      }
      }

    }
    myfile.close();
  }
  else
  {
    cout << "Unable to open file" << endl;
  }

  int* info = new int[2];
  info[0] = lineI;
  info[1] = valC;
  return info;

}



double startTimer()
{
    timeval tim;
    gettimeofday(&tim, NULL);
    double t1=tim.tv_sec+(tim.tv_usec/1000000.0);

    return t1;
}

double stopTimer()
{
    timeval tim;
    gettimeofday(&tim, NULL);
    double t2=tim.tv_sec+(tim.tv_usec/1000000.0);

    return t2;
}

double timeElapsed(double start, double stop)
{
    return stop-start;
}

void sleepForHowLong(int sleepTime)
{
    sleep(sleepTime);
}
char* fileNamePrefix(char* fileName)
{

    char toReturn[100];// = new char[100];
    char * pch;


    //cout << "splitting the string "<<fileName<< " on a '.'"<<endl;
    pch = strtok (fileName,".");

    strcpy(toReturn, "..");

    strcat(toReturn,pch);

    return toReturn;
}


void testMemoryData(int n, int d)
{
  //float p = 0.01234567;
  double p = 0.01234567;

  cout << "Testing n = " << n << ", and d = " << d << endl;

  double* pp = new double[n*d];
  for(int i = 0; i < n; i++)
  {
    for(int j = 0; j < d; j++)
    {
      pp[(i*d) + j] = p;
    }
  }

  cout << "All Data now in array!" << endl;

  //crude pause loop so you have time to check your system memory
  int t = 0;
  double pause = 200000000;
  for(double i = 0; i < pause; i++)
  {
    t = t * i;
    //something to force loop despite compiler optimiztion
  }

}



